package com.hjq.base.http.cookie

import okhttp3.Cookie
import okhttp3.HttpUrl
import java.util.ArrayList
import java.util.HashMap
import java.util.concurrent.ConcurrentHashMap

/**
 * Cookie内存缓存实现
 */
class MemoryCookieStore : CookieStore {
    companion object{
        private const val HOST_NAME_PREFIX = "host_"
        private const val COOKIE_NAME_PREFIX = "cookie_"
    }

    private val cookies = HashMap<String, ConcurrentHashMap<String, Cookie>>()

    override fun add(httpUrl: HttpUrl, cookie: Cookie) {
        if (!cookie.persistent()) {
            return
        }

        val name: String = cookieName(cookie)
        val hostKey: String? = hostName(httpUrl)

        if (!cookies.containsKey(hostKey)) {
            cookies[hostKey!!] = ConcurrentHashMap()
        }
        cookies[hostKey]!![name] = cookie
    }

    override fun add(httpUrl: HttpUrl, cookies: List<Cookie>?) {
        for (cookie in cookies!!) {
            if (isCookieExpired(cookie)) {
                continue
            }
            this.add(httpUrl, cookie)
        }
    }

    override fun get(httpUrl: HttpUrl): List<Cookie?> {
        return get(hostName(httpUrl)!!)
    }

    override fun getCookies(): List<Cookie?> {
        val result = ArrayList<Cookie?>()

        for (hostKey in cookies.keys) {
            result.addAll(get(hostKey))
        }

        return result
    }

    /** 获取cookie集合  */
    private operator fun get(hostKey: String): List<Cookie> {
        val result = ArrayList<Cookie>()
        if (cookies.containsKey(hostKey)) {
            val cookies: Collection<Cookie> = cookies[hostKey]!!.values
            for (cookie in cookies) {
                if (isCookieExpired(cookie)) {
                    this.remove(hostKey, cookie)
                } else {
                    result.add(cookie)
                }
            }
        }
        return result
    }

    override fun remove(httpUrl: HttpUrl, cookie: Cookie): Boolean {
        return this.remove(hostName(httpUrl), cookie)
    }

    /** 从缓存中移除cookie  */
    private fun remove(hostKey: String?, cookie: Cookie): Boolean {
        val name: String = cookieName(cookie)
        if (cookies.containsKey(hostKey) && cookies[hostKey]!!.containsKey(name)) {
            // 从内存中移除httpUrl对应的cookie
            cookies[hostKey]!!.remove(name)
            return true
        }
        return false
    }

    override fun removeAll(): Boolean {
        cookies.clear()
        return true
    }


    /** 判断cookie是否失效  */
    private fun isCookieExpired(cookie: Cookie): Boolean {
        return cookie.expiresAt() < System.currentTimeMillis()
    }

    private fun hostName(httpUrl: HttpUrl): String? {
        return if (httpUrl.host()
                .startsWith(HOST_NAME_PREFIX)
        ) httpUrl.host() else HOST_NAME_PREFIX + httpUrl.host()
    }

    private fun cookieName(cookie: Cookie): String {
        return cookie.name() + cookie.domain()
    }
}